const fs = require('fs-extra')
const path = require('path')
const inquirer = require('inquirer')
const spinner = require('ora')()
const download = require('download-git-repo')
const execa = require('execa')
const chalk = require('chalk')
const logSymbols = require('log-symbols')

const { 
	author, 
	clearScreen, 
	hasYarn 
} = require('./util')
const { 
	handlePresets, 
	presets, 
	presetNameList 
} = require('./preset')
  
let binPath = 'npm'
const optsCollection = {
	projectName: '',
	dir: '',
	frame: '',
	tpl: ''
}

async function selectTpl (optsCollection) {
	const { frame } = await inquirer.prompt([
		{
			type: 'list',
			name: 'frame',
			message: '请选择开发框架',
			choices: [
				{ name: 'Vue', value: 'vue' },
				{ name: 'React', value: 'react' }
			]
		}
	])
	const tpls = fs.readdirSync(path.join(__dirname, '../template'))
	const { tpl } = await inquirer.prompt([
		{
			type: 'list',
			name: 'tpl',
			message: '请选择模板',
			choices: tpls.filter(item => item.startsWith(frame))
		}
	])
	Object.assign(optsCollection, { frame, tpl })
}

function handleFile (copyPath, targetPath, fsEditor) {
	fs.readdir(copyPath, (err, files) => {
		if (err) {
			process.exit()
		} else {
			files.forEach(fileName => {
				const copyFilePath = path.join(copyPath, fileName)
				const targetFilePath = path.join(targetPath, fileName)
				fs.stat(copyFilePath, (err, stats) => {
					if (err) {
						console.log(err)
						process.exit()
					} else {
						const isFile = stats.isFile()
						const isDir = stats.isDirectory()
						if (isFile) {
							fsEditor.copyTpl(copyFilePath, targetFilePath, {
								author: 1
							})
							fsEditor.commit(err => {
								if (err) {
									console.log(
										chalk.red('> 模板生成失败！')
									)
									if (fs.existsSync(handleFile.dir)) {
										fs.rmdirSync(handleFile.dir)
									}
									process.exit()
								}
							})
						}
						if (isDir) {
							handleFile(copyFilePath, targetFilePath, fsEditor)
						}
					}
				})
			})
		}
	})
}
async function genTpl () {
	const { tpl, dir } = optsCollection

	const memFs = require('mem-fs')
	const editor = require('mem-fs-editor')
	const store = memFs.create()
	const fsEditor = editor.create(store)
	handleFile.dir = dir
	await handleFile(path.join(__dirname, '../template', tpl), dir, fsEditor)
}

async function combo () {
	await selectTpl(optsCollection)
	await handlePresets(optsCollection)
	await genTpl()
	clearScreen()
}

module.exports = async (projectName, mapOption) => {
	const { manually, force } = mapOption
	Object.assign(optsCollection, {
		projectName,
		dir: path.resolve(process.cwd(), projectName)
	})

	if (fs.existsSync(optsCollection.dir) && !force) {
		const { action } = await inquirer.prompt([
			{
				type: 'list',
				name: 'action',
				message: `${optsCollection.projectName}目录已存在`,
				choices: [
					{ name: '清空该目录', value: 'clean' },
					{ name: '另建目录', value: 'new' }
				]
			}
		])
		if (action === 'new') {
			const { newProjectName } = await inquirer.prompt([
				{
					type: 'input',
					name: 'newProjectName',
					message: '请输入项目名称',
					validate (input) {
						if (!input) {
							return '项目名不能为空！'
						}
						if (fs.existsSync(input)) {
							return '当前目录已经存在，请更换名称！'
						}
						return true
					}
				}
			])
			Object.assign(optsCollection, {
				projectName: newProjectName,
				dir: path.resolve(process.cwd(), newProjectName)
			})
		}
	}	

	if (!manually && presets.length) {
		const { curPreset } = await inquirer.prompt([
			{
				type: 'list',
				name: 'curPreset',
				message: '请选择预设',
				choices: [ ...presetNameList, 'manually' ]
			}
		])
		if (curPreset === 'manually') {
			await combo()
		} else {
			spinner.start('正在拉取模板...')
			const { tpl } = presets.find(item => curPreset === item.name)
			const { dir, projectName } = optsCollection 
			download(`github:${author}/${tpl}`, projectName, async err => {
				if (err) {
					process.exit()
				}
				spinner.stop()
				console.log(logSymbols.success, '模板下载完成！')
				const isYarn = hasYarn()
				binPath = isYarn ? 'yarn' : binPath
				const { isInstall } = await inquirer.prompt([
					{
						type: 'input',
						name: 'isInstall',
						message: '是否安装依赖？(Y/N)'
					}
				])
				if (isInstall && isInstall.toLowerCase() === 'y') {
					execa.sync(binPath, [ 'install' ], { cwd: dir, stdio: 'inherit' })
					clearScreen()
					console.log(
						'> Run:\n\n' +
            chalk.cyan(` ${chalk.gray('$')} cd ${projectName}\n`) +
            chalk.cyan(` ${chalk.gray('$')} ${isYarn ? 'yarn serve' : 'npm run serve'}`)
					)
				} else {
					clearScreen()
					console.log(
						'> Run:\n\n' +
            chalk.cyan(` ${chalk.gray('$')} cd ${projectName}\n`) +
            chalk.cyan(` ${chalk.gray('$')} ${isYarn ? 'yarn install' : 'npm run install'}\n`) +
            chalk.cyan(` ${chalk.gray('$')} ${isYarn ? 'yarn serve' : 'npm run serve'}`)
					)
				}
        
			})
		}
	} else {
		await combo()
	}

}